﻿using System;
using SoftwareConsulting.BI11.NumericalMethods.Curves;
using SoftwareConsulting.BI11.NumericalMethods.Statistics;
using SoftwareConsulting.BI11.Studio.InternalServices;

namespace SoftwareConsulting.BI11.NumericalMethods.Statistics
{
    /// <summary>
    /// Класс распределения, построенного на гистограмме
    /// </summary>
    public class HistogrammedDistribution : ProbabilityDensityFunction
    {
        private Histogram _histogram;

        /// <summary>
        /// Конструктор класса
        /// </summary>
        /// <param name="histogram"></param>
        public HistogrammedDistribution(Histogram histogram)
        {
            _histogram = histogram;
        }

        /// <summary>
        /// Возвращает среднее распределения
        /// </summary>
        public override double Average
        {
            get 
            { 
                return _histogram.Average; 
            }
            set 
            {
                Assert.Fail(Assert.Id.Assert00285);//для данного распределения не поддерживается
            }
        }

        /// <summary>
        /// Возвращает значение функции плотности распределения
        /// </summary>
        /// <param name="x"></param>
        /// <returns>вероятность, нахождения случайной переменной меньше или равной, чем X</returns>
        public override double GetDistributionValue(double x)
        {
            if (x < _histogram.Minimum)
                return 0;
            if (x < _histogram.Maximum)
                return _histogram.GetSumUpTo(x) / _histogram.TotalCount;
            return 1;
        }

        /// <summary>
        /// Возвращает вероятность нахождения случайной переменной в отрезке [x1;x2]
        /// </summary>
        /// <param name="x1"></param>
        /// <param name="x2"></param>
        /// <returns></returns>        
        public override double GetDistributionValue(double x1, double x2)
        {            
            return _histogram.GetCountsBetween(
                Math.Max(x1,_histogram.Minimum),
                Math.Min(x2,_histogram.Maximum)
                )
                / _histogram.TotalCount;
        }

        /// <summary>
        /// Возвращает эксцесс распределения
        /// </summary>
        public override double Kurtosis
        {
            get 
            { 
                return _histogram.Kurtosis; 
            }
        }

        /// <summary>
        /// Возвращает название распределения
        /// </summary>
        public override string Name
        {
            get 
            { 
                return "Experimental distribution"; 
            }
        }

        /// <summary>
        /// Возвращает/устанавливает параметры распределения
        /// </summary>
        public override double[] Parameters
        {
            get 
            { 
                return new double[0]; 
            }            
            set 
            {
                Assert.Fail(Assert.Id.Assert00286);//не поддерживается для данного распределения
            }
        }

        /// <summary>
        /// Возвращает коэффициент уклона распределения
        /// </summary>
        public override double Skewness
        {
            get 
            { 
                return _histogram.Skewness; 
            }
        }

        /// <summary>
        /// Вычисляет значение, основываясь на функции плотности
        /// </summary>
        /// <param name="x"></param>
        /// <returns></returns>
        public override double GetValue(double x)
        {
            return (x >= _histogram.Minimum || x < _histogram.Maximum) ? 
                _histogram.GetValueByX(x) / (_histogram.TotalCount + _histogram.BinWidth)
                : 
                0;
        }

        /// <summary>
        /// Возвращает дисперсию распределения
        /// </summary>
        public override double Variance
        {
            get 
            { 
                return _histogram.Variance; 
            }
        }
    }
}
